﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.RemoteRequest.Extensions;
using iWare.Wms.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Yitter.IdGenerator;
using HttpMethod = System.Net.Http.HttpMethod;

namespace iWare.Wms.Application
{
    /// <summary>
    /// AGV接口调用服务
    /// </summary>
    [Route("api/Agv")]
    [ApiDescriptionSettings("AGV服务", Name = "Agv", Order = 120)]
    public class AgvService : ControllerBase, IDynamicApiController, ITransient
    {
        private readonly IRepository<WareAgvTask, MasterDbContextLocator> _wareAgvTaskRep; //AGV任务仓储
        private readonly IRepository<WareContainer, MasterDbContextLocator> _wareContainerRep; //容器仓储
        private readonly IRepository<WareLocation, MasterDbContextLocator> _wareLocationRep; //库位仓储
        private readonly IRepository<WareTask, MasterDbContextLocator> _wareTaskRep; //任务仓储
        private readonly IRepository<WareStock, MasterDbContextLocator> _wareStockRep; //库存仓储
        private readonly IRepository<WareContainerVsMaterial, MasterDbContextLocator> _wareContainerVsMaterialRep; //容器与物料关系仓储
        private readonly IRepository<WareLocationVsContainer, MasterDbContextLocator> _wareLocationVsContainerRep; //库位与容器关系仓储
        private readonly IRepository<WareSortOrder, MasterDbContextLocator> _wareSortOrderRep; //分拣明细表
        private readonly IRepository<WareDeviceFault, MasterDbContextLocator> _wareDeviceFaultRep; //设备报警表

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareAgvTaskRep"></param>
        /// <param name="wareContainerRep"></param>
        /// <param name="wareLocationRep"></param>
        /// <param name="wareTaskRep"></param>
        /// <param name="wareStockRep"></param>
        /// <param name="wareContainerVsMaterialRep"></param>
        /// <param name="wareLocationVsContainerRep"></param>
        /// <param name="wareSortOrderRep"></param>
        /// <param name="wareDeviceFaultRep"></param>
        public AgvService(
            IRepository<WareAgvTask, MasterDbContextLocator> wareAgvTaskRep,
            IRepository<WareContainer, MasterDbContextLocator> wareContainerRep,
            IRepository<WareLocation, MasterDbContextLocator> wareLocationRep,
            IRepository<WareTask, MasterDbContextLocator> wareTaskRep,
            IRepository<WareStock, MasterDbContextLocator> wareStockRep,
            IRepository<WareContainerVsMaterial, MasterDbContextLocator> wareContainerVsMaterialRep,
            IRepository<WareLocationVsContainer, MasterDbContextLocator> wareLocationVsContainerRep,
            IRepository<WareSortOrder, MasterDbContextLocator> wareSortOrderRep,
            IRepository<WareDeviceFault, MasterDbContextLocator> wareDeviceFaultRep
        )
        {
            _wareAgvTaskRep = wareAgvTaskRep;
            _wareContainerRep = wareContainerRep;
            _wareLocationRep = wareLocationRep;
            _wareTaskRep = wareTaskRep;
            _wareStockRep = wareStockRep;
            _wareContainerVsMaterialRep = wareContainerVsMaterialRep;
            _wareLocationVsContainerRep = wareLocationVsContainerRep;
            _wareSortOrderRep = wareSortOrderRep;
            _wareDeviceFaultRep = wareDeviceFaultRep;
        }
        #endregion

        /// <summary>
        /// 查询车辆列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("QueryTransportCarList")]
        [AllowAnonymous]
        public async Task<QueryTransportCarListOutput> QueryTransportCarList([FromBody] QueryTransportCarNameInput input)
        {
            try
            {
                //查询车辆列表操作
                string url = "http://10.10.10.59:55200/v1/vehicles";

                // 写日志文件
                Log.Error($"[QueryCarList][url:{url}]");

                var response = await url.GetAsAsync<QueryTransportCarListOutput>();

                // 写日志文件
                Log.Error($"[QueryCarList][response:{response.ToJson()}]");

                return response;
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        /// <summary>
        /// 查询指定名称的车辆
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("QueryTransportCarName")]
        [AllowAnonymous]
        public async Task<QueryTransportCarNameOutput> QueryTransportCarName([FromBody] QueryTransportCarNameInput input)
        {
            try
            {
                //查询指定名称的车辆操作
                string url = "http://10.10.10.59:55200/v1/vehicles/" + input.Name;

                // 写日志文件
                Log.Error($"[QueryTransportCarName][Name:{input.Name}][url:{url}]");

                var response = await url.GetAsAsync<QueryTransportCarNameOutput>();

                // 写日志文件
                Log.Error($"[QueryTransportCarName][Name:{input.Name}][response:{response.ToJson()}]");

                return response;
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        /// <summary>
        /// 根据订单名称查询单个订单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("QueryTransportOrders")]
        [AllowAnonymous]
        public async Task<QueryTransportOrdersOutput> QueryTransportOrders([FromBody] QueryTransportOrdersInput input)
        {
            try
            {
                //根据订单名称查询单个订单操作
                string url = "http://10.10.10.59:55200/v1/transportOrders/" + input.Name;

                // 写日志文件
                Log.Error($"[QueryTransportOrders][Name:{input.Name}][url:{url}]");

                var response = await url.GetAsAsync<QueryTransportOrdersOutput>();

                // 写日志文件
                Log.Error($"[QueryTransportOrders][Name:{input.Name}][response:{response.ToJson()}]");

                return response;
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        /// <summary>
        /// 创建指定名称的订单
        /// </summary>
        /// <returns></returns>
        [HttpPost("CreateTransportOrders")]
        [AllowAnonymous]
        public async Task<CreateTransportOrdersOutput> CreateTransportOrders([FromBody] CreateTransportOrdersInput input)
        {
            try
            {
                var proList = new List<PropertiesInput>();
                var proModel = new PropertiesInput
                {
                    key = "code",
                    value = "10010001"
                };
                proList.Add(proModel);
                input.properties = proList;

                //创建指定名称的订单操作
                string url = "http://10.10.10.59:55200/v1/transportOrders/" + input.TaskNo;

                // 写日志文件
                Log.Error($"[CreateTransportOrders][TaskNo:{input.TaskNo}][url:{url}]");

                var response = await url.SetHttpMethod(HttpMethod.Post)
                                        .SetBody(new Dictionary<string, object> {
                                            { "intendedVehicle", input.intendedVehicle },
                                            { "destinations", input.destinations },
                                            { "properties", input.properties},
                                        }, "application/json")
                                        .PostAsAsync<CreateTransportOrdersOutput>();

                // 写日志文件
                Log.Error($"[CreateTransportOrders][TaskNo:{input.TaskNo}][response:{response.ToJson()}]");

                return response;
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        /// <summary>
        /// 创建取货指令订单
        /// </summary>
        /// <returns></returns>
        [HttpPost("CreateLoadOrders")]
        [AllowAnonymous]
        public async Task<CreateTransportOrdersOutput> CreateLoadOrders([FromBody] CreateOrdersedInput input)
        {
            try
            {
                //创建指定名称的订单操作
                string url = "http://10.10.10.59:55200/v1/loadTransportOrders";

                // 写日志文件
                Log.Error($"[CreateTransportOrders][TaskNo:{input.TaskNo}][url:{url}]");

                var response = await url.SetHttpMethod(HttpMethod.Post)
                                        .SetBody(new Dictionary<string, object> {
                                            { "orderName", input.TaskNo },
                                            { "locationName", input.locationName },
                                            { "operation", input.operation},
                                        }, "application/json")
                                        .PostAsAsync<CreateTransportOrdersOutput>();

                // 写日志文件
                Log.Error($"[CreateTransportOrders][TaskNo:{input.TaskNo}][response:{response.ToJson()}]");

                return response;
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        /// <summary>
        /// 创建放货指令订单
        /// </summary>
        /// <returns></returns>
        [HttpPost("CreateUnloadOrders")]
        [AllowAnonymous]
        public async Task<CreateTransportOrdersOutput> CreateUnloadOrders([FromBody] CreateOrdersedInput input)
        {
            try
            {
                //创建指定名称的订单操作
                string url = "http://10.10.10.59:55200/v1/unloadTransportOrders";

                // 写日志文件
                Log.Error($"[CreateTransportOrders][TaskNo:{input.TaskNo}][url:{url}]");

                var response = await url.SetHttpMethod(HttpMethod.Post)
                                        .SetBody(new Dictionary<string, object> {
                                            { "orderName", input.TaskNo },
                                            { "locationName", input.locationName },
                                            { "operation", input.operation},
                                        }, "application/json")
                                        .PostAsAsync<CreateTransportOrdersOutput>();

                // 写日志文件
                Log.Error($"[CreateTransportOrders][TaskNo:{input.TaskNo}][response:{response.ToJson()}]");

                return response;
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        #region AGV任务回调
        /// <summary>
        /// AGV任务回调接口，AGV主动请求
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("UpdateAgvState")]
        [AllowAnonymous]
        [UnifyResult(typeof(object))]
        public async Task<object> UpdateAgvState([FromBody] AgvInput input)
        {
            try
            {
                // 写日志文件
                Log.Error("[AGV回调任务接口]接收参数:" + input.ToJson());
                // 根据任务号查询是否有任务存在
                var returnTaskNo = input.TransportOrder.Split('-')[0];
                var wareAgvTask = await _wareAgvTaskRep.FirstOrDefaultAsync(z => z.TransportOrder == returnTaskNo && z.AgvState != "FINISHED");
                if (wareAgvTask == null) throw Oops.Oh("AGV任务不存在");
                if (wareAgvTask.AgvState == "FINISHED") throw Oops.Oh("AGV任务已经完成");
                // 更新agv任务状态
                wareAgvTask.AgvState = input.AgvState;
                await _wareAgvTaskRep.UpdateAsync(wareAgvTask);
                // 检查托盘
                var wareContainer = await _wareContainerRep.Where(z => z.Code == wareAgvTask.ContainerCode).FirstOrDefaultAsync();

                // 查询容器与物料关系
                var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
                .Where(p => p.WareContainer.Code == wareContainer.Code && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

                if (input.AgvState == "FINISHED")// AGV任务状态完成
                {
                    //修改agv任务状态
                    wareAgvTask.AgvState = "FINISHED";
                    await _wareAgvTaskRep.UpdateAsync(wareAgvTask);

                    if (wareAgvTask.TaskType == "入库")
                    {
                        if (wareContainer.Code.StartsWith("TJ")) //立体库库区
                        {

                            var taskModle = await _wareTaskRep.FirstOrDefaultAsync(z => z.TaskNo == wareAgvTask.TransportOrder);
                            if (taskModle != null)
                            {
                                taskModle.IsRead = true;
                                await _wareTaskRep.UpdateAsync(taskModle);
                            }
                        }
                        else //平库库区
                        {
                            //查询当前执行的任务
                            var taskMode = _wareTaskRep.FirstOrDefault(z => z.TaskNo == returnTaskNo);
                            if (wareAgvTask.EndPlace == "9067")
                            {
                                taskMode.TaskStatus = TaskStatusEnum.Progress;
                                await _wareTaskRep.UpdateAsync(taskMode);
                            }
                            else
                            {
                                //任务强制完成
                                await TaskFinish(new TaskCallbackInput
                                {
                                    Id = taskMode.Id
                                });
                            }
                        }

                        var taskModetwo = await _wareTaskRep.Where(z => z.TaskNo == returnTaskNo && z.TaskStatus != TaskStatusEnum.Complete).FirstOrDefaultAsync();
                        var LontionMode = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == taskModetwo.FromLocationCode && z.LocationStatus == LocationStatusEnum.daichu);
                        if (LontionMode != null)
                        {
                            //删除agv分拣库位容器关系
                            var LontionVSContion = await _wareLocationVsContainerRep.FirstOrDefaultAsync(z => z.LocationCode == LontionMode.Code && z.LocationVsContainerStatus == CommonStatus.ENABLE);
                            if (LontionVSContion == null) throw Oops.Oh("AGV分拣库位关系不存在!");
                            await _wareLocationVsContainerRep.DeleteAsync(LontionVSContion);
                            //更新agv分拣库位关系
                            LontionMode.LocationStatus = LocationStatusEnum.kongxian;
                            await _wareLocationRep.UpdateAsync(LontionMode);
                        }
                    }
                    else if (wareAgvTask.TaskType == "出库")
                    {
                        var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == wareAgvTask.StartPlace);

                        if (locationModel.AreaID == 374444843716677) //立体库库区
                        {
                            //查询当前执行的任务
                            var taskMode = _wareTaskRep.FirstOrDefault(z => z.TaskNo == input.TransportOrder);
                            //任务强制完成
                            await TaskFinish(new TaskCallbackInput
                            {
                                Id = taskMode.Id
                            });

                            // 更新agv库区状态为存货
                            var wareAgvLocationModel = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == wareAgvTask.EndPlace);
                            if (wareAgvLocationModel == null) throw Oops.Oh("站点信息不存在");
                            wareAgvLocationModel.LocationStatus = LocationStatusEnum.cunhuo;
                            await _wareLocationRep.UpdateAsync(wareAgvLocationModel);

                            //新增库位托盘绑定关系
                            var wareLocationVsContainerModel = new WareLocationVsContainer()
                            {
                                LocationId = wareAgvLocationModel.Id,
                                LocationCode = wareAgvLocationModel.Code,
                                ContainerId = wareContainer.Id,
                                ContainerCode = wareContainer.Code,
                                LocationVsContainerStatus = CommonStatus.ENABLE
                            };
                            await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);

                        }
                        else //平库库区
                        {
                            //查询当前执行的任务
                            var taskMode = _wareTaskRep.FirstOrDefault(z => z.TaskNo == input.TransportOrder);
                            //任务强制完成
                            await TaskFinish(new TaskCallbackInput
                            {
                                Id = taskMode.Id
                            });

                            // 更新站点状态为存货
                            var wareAgvLocationModel = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == wareAgvTask.EndPlace);
                            if (wareAgvLocationModel == null) throw Oops.Oh("站点信息不存在");
                            wareAgvLocationModel.LocationStatus = LocationStatusEnum.cunhuo;

                            await _wareLocationRep.UpdateAsync(wareAgvLocationModel);

                            //新增库位托盘绑定关系
                            var wareLocationVsContainerModel = new WareLocationVsContainer()
                            {
                                LocationId = wareAgvLocationModel.Id,
                                LocationCode = wareAgvLocationModel.Code,
                                ContainerId = wareContainer.Id,
                                ContainerCode = wareContainer.Code,
                                LocationVsContainerStatus = CommonStatus.ENABLE
                            };
                            await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);
                        }
                    }
                    else if (wareAgvTask.TaskType == "余料回库")
                    {
                        if (wareContainer.Code.StartsWith("TJ")) //立体库库区
                        {

                            var taskModle = await _wareTaskRep.FirstOrDefaultAsync(z => z.TaskNo == wareAgvTask.TransportOrder);
                            if (taskModle != null)
                            {
                                taskModle.IsRead = true;
                                await _wareTaskRep.UpdateAsync(taskModle);
                            }
                        }
                        else //平库库区
                        {
                            //查询当前执行的任务
                            var taskMode = _wareTaskRep.FirstOrDefault(z => z.TaskNo == returnTaskNo);
                            if (wareAgvTask.EndPlace == "9067")
                            {
                                taskMode.TaskStatus = TaskStatusEnum.Progress;
                                await _wareTaskRep.UpdateAsync(taskMode);
                                //await GetAgvWeight(new GetAgvInput
                                //{
                                //    TransportOrder = input.TransportOrder,
                                //    AgvWeight = "1"
                                //});
                            }
                            else
                            {
                                //任务完成
                                await TaskFinish(new TaskCallbackInput
                                {
                                    Id = taskMode.Id
                                });
                            }
                        }
                    }

                }
                return XnRestfulResultProvider.RESTfulResult();

            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }
        #endregion

        #region AGV报警回调
        /// <summary>
        /// AGV报警回调接口，AGV主动请求
        /// </summary>
        /// <returns></returns>
        [HttpPost("AGVAAlarm")]
        [AllowAnonymous]
        [UnifyResult(typeof(object))]
        public async Task<object> AGVAAlarm([FromBody] AGVAAlarmInput input)
        {
            // 写日志文件
            Log.Error("[AGV报警回调接口]接收参数:" + input.ToJson());

            //根据几号车查询数据是否已存在
            var wareDeviceFault = await _wareDeviceFaultRep.FirstOrDefaultAsync(u => u.DeviceName == input.CarNo);

            if (wareDeviceFault == null) //不存在新增报警
            {
                wareDeviceFault = new WareDeviceFault()
                {
                    DeviceNo = input.CarNo, //设备编号
                    DeviceName = input.CarNo, //设备名称
                    StartTime = input.AlarmTime, //报警时间
                    FaultName = input.AlarmMessage, //故障描述
                    FaultCode = input.AlarmCode //故障代码
                };
                await _wareDeviceFaultRep.InsertAsync(wareDeviceFault);
            }
            else //已存在更新报警信息
            {
                wareDeviceFault.StartTime = input.AlarmTime;
                wareDeviceFault.FaultName = input.AlarmMessage;
                wareDeviceFault.FaultCode = input.AlarmCode;
                await _wareDeviceFaultRep.UpdateAsync(wareDeviceFault);
            }

            return XnRestfulResultProvider.RESTfulResult();
        }
        #endregion

        /// <summary>
        /// AGV获取重量回调接口，AGV主动请求
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("GetAgvWeight")]
        [AllowAnonymous]
        [UnifyResult(typeof(object))]
        public async Task<object> GetAgvWeight([FromBody] GetAgvInput input)
        {
            try
            {
                // 写日志文件
                Log.Error("[AGV回调任务接口]接收参数:" + input.ToJson());
                var returnTaskNo = input.TransportOrder.Split('-')[0];
                var taskModel = await _wareTaskRep.FirstOrDefaultAsync(p => p.TaskNo == returnTaskNo);
                if (taskModel != null)
                {
                    if (input.AgvWeight == "1") taskModel.Weight = "0.9T";
                    if (input.AgvWeight == "2") taskModel.Weight = "1.2T";
                    if (input.AgvWeight == "3") taskModel.Weight = "1.5T";
                }
                //查询库位信息,如果为空说明没有指定库位
                var wareLocation = await _wareLocationRep.Where(z => z.Code == taskModel.ToLocationCode).FirstOrDefaultAsync();
                if (wareLocation == null)
                {
                    taskModel.IsRead = true;
                    await _wareTaskRep.UpdateAsync(taskModel);
                    return XnRestfulResultProvider.RESTfulResult();
                }
                //修改库位信息为待入
                wareLocation.LocationStatus = LocationStatusEnum.dairu;
                await _wareLocationRep.UpdateAsync(wareLocation);


                //根据库位获取对应的放货层
                var layNumber = 0;
                if (wareLocation.RowNo == 6)
                {
                    if (wareLocation.LayerNo == 5) layNumber = wareLocation.LayerNo + 6;
                    else layNumber = wareLocation.LayerNo + 5;

                }
                else
                {
                    if (wareLocation.LayerNo == 1) layNumber = wareLocation.LayerNo - 1;
                    else layNumber = wareLocation.LayerNo;
                }
                //创建第二段AGV任务
                var agvModel = new CreateOrdersedInput()
                {
                    TaskNo = returnTaskNo + "-2",
                    locationName = wareLocation.OriginalLocationCode,
                    operation = "Unload cargo:" + layNumber.ToString("00")
                };
                var createTransportOrdersOutput = await CreateUnloadOrders(agvModel);

                if (createTransportOrdersOutput.result == "success")
                {
                    // 创建AGV入库任务
                    var wareAgvTask = new WareAgvTask()
                    {
                        TaskType = "入库",
                        StartPlace = "9067", //地面站点/上料口
                        EndPlace = wareLocation.Code, //平库原库位编号
                        TransportOrder = returnTaskNo,
                        AgvState = "TRAVELLING",
                        ContainerCode = taskModel.ContainerCode,
                        CreatedUserName = taskModel.CreatedUserName
                    };
                    await _wareAgvTaskRep.InsertAsync(wareAgvTask);
                }
                return XnRestfulResultProvider.RESTfulResult();
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        /// <summary>
        /// 从输送线上发AGV任务，指定站点发送
        /// </summary>
        /// <returns></returns>
        [HttpPost("FastAddAgvTask")]
        public async Task FastAddAgvTask([FromBody] FastAddAgvTaskInput input)
        {
            #region 判断输送线上是否还有任务
            var wareTask = await _wareTaskRep.DetachedEntities.Where(z => z.IsShuSongXian == YesOrNot.Y
            && z.TaskStatus == TaskStatusEnum.Complete && z.TaskType == TaskType.Out).FirstOrDefaultAsync();
            if (wareTask != null)
            {
                // 根据站点判断状态是否为空闲
                var wareSiteShuSongXianTask = await _wareLocationRep.FirstOrDefaultAsync(z => z.Code == input.LocationName && z.LocationStatus == LocationStatusEnum.kongxian);
                if (wareSiteShuSongXianTask == null) throw Oops.Oh("站点有货不能存放");

                var taskNoShuSongXian = YitIdHelper.NextId().ToString(); //系统生成任务号

                #region 调用AGV服务创建指定名称的订单
                var createTransportOrders = new CreateTransportOrdersInput();
                createTransportOrders.TaskNo = taskNoShuSongXian;
                createTransportOrders.intendedVehicle = "Vehicle-01"; //立体库执行车辆
                var destList = new List<DestinationsInput>();
                var dest1 = new DestinationsInput()
                {
                    locationName = "Location-0011", //[8052/Location-0011] 出库对应的输送线
                    operation = "Load cargo:01" //输送线层数是1，Load是取货
                };
                var dest2 = new DestinationsInput()
                {
                    locationName = input.LocationName, //地面站点/放料口
                    operation = "Unload cargo:00"  //地面层数是0，Unload是放货
                };
                destList.Add(dest1);
                destList.Add(dest2);

                createTransportOrders.destinations = destList;
                var createTransportOrdersOutput = await CreateTransportOrders(createTransportOrders);
                // 写日志文件
                Log.Error($"[FastAddAgvTask-从输送线上发AGV任务][createTransportOrdersOutput:{createTransportOrdersOutput.ToJson()}]");
                #endregion

                var wareContionVSLocat = await _wareLocationVsContainerRep.FirstOrDefaultAsync(z => z.LocationCode == wareSiteShuSongXianTask.Code && z.LocationVsContainerStatus == CommonStatus.ENABLE);

                var wareCotain = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == wareContionVSLocat.ContainerCode);

                if (createTransportOrdersOutput.result == "success")
                {
                    #region 创建AGV出库任务
                    var wareAgvTaskByShuSongXian = new WareAgvTask()
                    {
                        TaskType = "出库",
                        StartPlace = "Location-0015", //[Location-0015] 出库对应的输送线
                        EndPlace = input.LocationName, //地面站点/放料口
                        TransportOrder = taskNoShuSongXian,
                        AgvState = "TRAVELLING",
                        ContainerCode = wareTask.ContainerCode,
                        CreatedUserName = wareTask.CreatedUserName
                    };
                    await _wareAgvTaskRep.InsertAsync(wareAgvTaskByShuSongXian);
                    #endregion

                    #region 更新站点状态和容器编号（agv任务完成后，更新站点状态为存货）
                    if (wareSiteShuSongXianTask != null)
                    {
                        //更新agv库区状态
                        wareSiteShuSongXianTask.LocationStatus = LocationStatusEnum.dairu;
                        await _wareLocationRep.UpdateAsync(wareSiteShuSongXianTask);

                        //构建容器与agv库位关系表
                        var wareLocationVsContainerModel = new WareLocationVsContainer()
                        {
                            LocationId = wareSiteShuSongXianTask.Id,
                            LocationCode = wareSiteShuSongXianTask.Code,
                            ContainerId = wareCotain.Id,
                            ContainerCode = wareCotain.Code,
                            LocationVsContainerStatus = CommonStatus.ENABLE
                        };
                        await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);
                    }
                    #endregion
                }
            }
            #endregion
        }

        /// <summary>
        /// 快速入库,不对接AGV
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("FastWarehousing")]
        [UnifyResult(typeof(object))]
        public async Task<object> FastWarehousing([FromBody] FastWarehousingInput input)
        {
            try
            {
                // 写日志文件
                Log.Error("[快速入库,不对接AGV]接收参数:" + input.ToJson());

                // 检查托盘
                var wareContainer = await _wareContainerRep.Where(z => z.Code == input.ContainerCode).FirstOrDefaultAsync();

                // 查询容器与物料关系
                var WareContainerVsMaterials = await _wareContainerVsMaterialRep.DetachedEntities
                .Where(p => p.WareContainer.Code == wareContainer.Code && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

                try
                {
                    var orderNo = "N/A";
                    if (WareContainerVsMaterials.Count > 0) orderNo = WareContainerVsMaterials.FirstOrDefault().OrderNo;

                    var taskNo = YitIdHelper.NextId().ToString(); //系统生成任务号

                    // 根据容器编号判断是否有未完成的任务
                    var isTaskExis = await _wareTaskRep.AnyAsync(z => z.ContainerCode == wareContainer.Code && z.TaskType == TaskType.In
                    && z.TaskStatus != TaskStatusEnum.Complete);
                    if (isTaskExis) return XnRestfulResultProvider.RESTfulResult();

                    //1.创建任务
                    var taskModel = new WareTask()
                    {
                        OrderNo = orderNo,
                        TaskNo = YitIdHelper.NextId().ToString(),
                        TaskType = TaskType.In,
                        TaskModel = TaskModel.ZIDONG,
                        TaskName = orderNo == "N/A" ? TaskNameConst.KongTuo_LitikuAutomaticIn : TaskNameConst.Litiku_AutomaticIn,
                        TaskStatus = TaskStatusEnum.NotProgress,
                        Priority = 1,
                        ContainerCode = wareContainer.Code,
                        FromLocationCode = "Location-0012", //对应入库的输送线
                        ToLocationCode = "N/A"
                    };
                    await _wareTaskRep.InsertAsync(taskModel);

                    //执行完成调用工控机上的入库授权服务
                    await "http://10.10.10.59:8011/LesApi.ashx".GetAsync();
                }
                catch (Exception ex)
                {
                    throw Oops.Oh("[FastWarehousing]快速入库,不对接AGV异常：" + ex.StackTrace);
                }
                finally
                {
                }

                return XnRestfulResultProvider.RESTfulResult();
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ex.Message);
            }
        }

        #region 其他方法
        /// <summary>
        /// 任务完成
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [NonAction]
        public async Task TaskFinish([FromBody] TaskCallbackInput input)
        {
            var taskModel = await _wareTaskRep.FirstOrDefaultAsync(p => p.Id == input.Id);
            if (taskModel.TaskStatus == TaskStatusEnum.Complete) throw Oops.Oh("任务已完成!");
            if (taskModel.TaskType == TaskType.In)  //入库
            {
                //检查容器
                var containerModel = await _wareContainerRep.FirstOrDefaultAsync(n => n.Code == taskModel.ContainerCode);
                //if (taskModel.OrderNo != "N/A" && containerModel.ContainerStatus != ContainerStatusEnum.zupan) throw Oops.Oh("托盘未进行组盘!");
                //用于判断空托
                if (taskModel.OrderNo == "N/A" && containerModel.ContainerStatus != ContainerStatusEnum.kongxian) throw Oops.Oh("托盘信息不存在!");

                //检查库位
                var locationModel = await _wareLocationRep.DetachedEntities.Where(p => p.Code == taskModel.ToLocationCode).FirstOrDefaultAsync();
                if (locationModel == null) throw Oops.Oh("库位不存在!");
                if (locationModel.LocationStatus != LocationStatusEnum.dairu) throw Oops.Oh("库位异常货!");

                //获取库位容器关系
                var wareLocationVsContainerModel = await _wareLocationVsContainerRep.FirstOrDefaultAsync(p => p.ContainerCode == containerModel.Code
                     && p.LocationVsContainerStatus == CommonStatus.ENABLE);
                if (wareLocationVsContainerModel == null)
                {
                    // 创建容器与库位关系表
                    wareLocationVsContainerModel = new WareLocationVsContainer()
                    {
                        LocationId = locationModel.Id,
                        LocationCode = locationModel.Code,
                        ContainerId = containerModel.Id,
                        ContainerCode = containerModel.Code,
                        LocationVsContainerStatus = CommonStatus.ENABLE
                    };
                    await _wareLocationVsContainerRep.InsertAsync(wareLocationVsContainerModel);
                }
                //更新容器状态为库位
                containerModel.ContainerStatus = ContainerStatusEnum.kuwei;
                await _wareContainerRep.UpdateAsync(containerModel);

                //更新库位状态为存货
                locationModel.LocationStatus = LocationStatusEnum.cunhuo;
                if (taskModel.OrderNo == "N/A") locationModel.IsEmptyContainer = YesOrNot.Y;
                else locationModel.IsEmptyContainer = YesOrNot.N;
                await _wareLocationRep.UpdateAsync(locationModel);

                //更新任务状态为完成
                taskModel.TaskStatus = TaskStatusEnum.Complete;
                await _wareTaskRep.UpdateAsync(taskModel);

                //物料托盘关系表
                var wmsMaterialContainerList = await _wareContainerVsMaterialRep.DetachedEntities
                    .Where(p => p.OrderNo == taskModel.OrderNo).ToListAsync();
                //更新库存
                foreach (var item in wmsMaterialContainerList)
                {
                    // 更新库存
                    var stockDetailModel = await _wareStockRep.FirstOrDefaultAsync(n => n.ContainerCode == item.ContainerCode
                    && n.ProjectCode == item.ProjectCode && n.Code == item.Code && n.SpecificationModel == item.SpecificationModel);

                    if (stockDetailModel != null)
                    {
                        stockDetailModel.StockQuantity = item.BindQuantity;
                        stockDetailModel.LocationCode = locationModel.Code;
                        stockDetailModel.CurrentQuantity = item.BindQuantity;
                        stockDetailModel.ProjectCode = item.ProjectCode;
                        stockDetailModel.ExpirationTime = item.ExpirationTime;
                        await _wareStockRep.UpdateAsync(stockDetailModel);
                    }
                    else
                    {
                        stockDetailModel = new WareStock()
                        {
                            ProjectCode = item.ProjectCode,
                            Code = item.Code,
                            Name = item.Name,
                            SpecificationModel = item.SpecificationModel,
                            Unit = item.Unit ?? "",
                            StockQuantity = item.BindQuantity,
                            CurrentQuantity = item.BindQuantity,
                            ContainerCode = item.ContainerCode,
                            LocationCode = locationModel.Code,
                            XuHao = item.XuHao ?? "",
                            BrandName = item.BrandName ?? "",
                            ExpirationTime = item.ExpirationTime,
                            CreatedTime = DateTimeOffset.Now,
                            UpdatedTime = DateTimeOffset.Now
                        };
                        await _wareStockRep.InsertAsync(stockDetailModel);
                    }
                }

                //空托
                if (taskModel.OrderNo == "N/A")
                {
                    var stockModel = new WareStock()
                    {
                        ProjectCode = "N/A",
                        Code = "N/A",
                        Name = "N/A",
                        SpecificationModel = "N/A",
                        Unit = "N/A",
                        StockQuantity = 1,
                        CurrentQuantity = 1,
                        ContainerCode = containerModel.Code,
                        LocationCode = locationModel.Code,
                        XuHao = "N/A",
                        BrandName = ""
                    };
                    await _wareStockRep.InsertAsync(stockModel);
                }
            }
            else //出库
            {
                //库位信息
                var locationModel = await _wareLocationRep.FirstOrDefaultAsync(p => p.Code == taskModel.FromLocationCode);
                if (locationModel == null) throw Oops.Oh("库位不存在!");
                if (locationModel.LocationStatus != LocationStatusEnum.daichu) throw Oops.Oh("库位异常货!");

                //容器信息
                var containerModel = await _wareContainerRep.FirstOrDefaultAsync(n => n.Code == taskModel.ContainerCode &&
                n.ContainerStatus == ContainerStatusEnum.kuwei);
                if (containerModel == null) throw Oops.Oh("托盘信息不存在!");

                //库位容器关系
                var lvcModel = await _wareLocationVsContainerRep.FirstOrDefaultAsync(p => p.ContainerCode == taskModel.ContainerCode
                   && p.ContainerId == containerModel.Id && p.LocationCode == locationModel.Code && p.LocationId == locationModel.Id
                   && p.LocationVsContainerStatus == CommonStatus.ENABLE);
                if (lvcModel == null) throw Oops.Oh("库位容器关系不存在!");


                //关系对应出库的物料状态
                var materialContainersList = await _wareContainerVsMaterialRep.Where(p => p.ContainerCode == taskModel.ContainerCode
                && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();

                //库存
                var materialStockList = await _wareStockRep.Where(n => n.ContainerCode == taskModel.ContainerCode
                && n.LocationCode == taskModel.FromLocationCode).ToListAsync();

                //构建出库物料和托盘关系
                var OrderNo = YitIdHelper.NextId().ToString();
                foreach (var item in materialContainersList)
                {
                    item.ContainerVsMaterialStatus = CommonStatus.DELETED;
                    await _wareContainerVsMaterialRep.UpdateAsync(item);
                    //新增正常新的组盘关系
                    var enableModel = new WareContainerVsMaterial()
                    {
                        ContainerId = item.ContainerId,
                        ContainerCode = item.ContainerCode,
                        ProjectCode = item.ProjectCode,
                        XuHao = item.XuHao,
                        Code = item.Code,
                        Name = item.Name,
                        SpecificationModel = item.SpecificationModel,
                        Unit = item.Unit,
                        InspectionMethod = item.InspectionMethod,
                        BrandName = item.BrandName,
                        MaterialId = item.MaterialId,
                        BindQuantity = item.BindQuantity,
                        ContainerVsMaterialStatus = CommonStatus.ENABLE,
                        ExpirationTime = item.ExpirationTime,
                        OrderNo = OrderNo
                    };
                    await _wareContainerVsMaterialRep.InsertNowAsync(enableModel);
                }
                //禁用托盘库位关系
                lvcModel.LocationVsContainerStatus = CommonStatus.DELETED;
                await _wareLocationVsContainerRep.UpdateAsync(lvcModel);

                // 更新容器状态为分拣
                if (taskModel.OrderNo == "N/A")
                {
                    containerModel.ContainerStatus = ContainerStatusEnum.kongxian;
                }
                else
                {
                    var isExit = await _wareSortOrderRep.AnyAsync(p => p.ContainerCode == containerModel.Code && p.SortStatus != SortStatusEnum.Completed);
                    if (isExit)
                    {
                        containerModel.ContainerStatus = ContainerStatusEnum.fenjian;
                    }
                    else
                    {
                        containerModel.ContainerStatus = ContainerStatusEnum.zupan;
                    }
                }
                await _wareContainerRep.UpdateAsync(containerModel);

                //更新库位状态为“空闲”
                locationModel.LocationStatus = LocationStatusEnum.kongxian;
                locationModel.IsEmptyContainer = YesOrNot.N;
                await _wareLocationRep.UpdateAsync(locationModel);
                //更新任务状态
                taskModel.TaskStatus = TaskStatusEnum.Complete;
                await _wareTaskRep.UpdateAsync(taskModel);

                //清除库存对应库位
                //修改库存
                foreach (var item in materialStockList)
                {
                    item.LocationCode = "N/A";
                    //空托
                    if (taskModel.OrderNo == "N/A")
                    {
                        item.StockQuantity = 0;
                        item.CurrentQuantity = 0;
                    }
                    await _wareStockRep.UpdateAsync(item);
                }
            }

        }
        #endregion
    }
}
